package main

import (
	"fmt"
	"net"
	"strings"

	"go-frame/service"
)

func main() {
	// 监听端口
	groupMsgQueue := service.NewQueue(10)
	listen, err := net.Listen("tcp", "127.0.0.1:20000")
	if err != nil {
		fmt.Println("listen failed, err:", err)
		return
	}

	onlineUsers := make(map[string]net.Conn)

	for {
		// 建立连接
		conn, err := listen.Accept()
		if err != nil {
			fmt.Println("accept failed, err:", err)
			continue
		}

		// 启动一个单独的goroutine去处理连接
		go process(conn, onlineUsers, groupMsgQueue)
	}
}

func process(conn net.Conn, onlineUsers map[string]net.Conn, groupMsgQueue *service.Queue) {
	defer conn.Close() // 关闭连接
	for {
		// 创建一个切片
		buf := make([]byte, 1024)
		// 读取数据
		n, err := conn.Read(buf)
		if err != nil {
			fmt.Println("read from conn failed, err:", err)
			break
		}
		// 输出客户端发送的数据
		// li|name  name登录
		// lo|name  name登出
		// co  查看在线用户
		// gs|name|message    name发送消息
		// gr|name|message    name接收消息

		m := string(buf[:n])
		//去掉换行符
		m = strings.Replace(m, "\n", "", -1)
		m = strings.Replace(m, "\r", "", -1)

		cmdSplit := strings.Split(m, "|")
		//spew.Dump(cmdSplit)

		cmd := cmdSplit[0]
		//fmt.Println("cmd:", cmd)
		switch cmd {
		case "li":
			if len(cmdSplit) < 2 {
				fmt.Println("参数数量有问题")
				break
			}
			nickname := cmdSplit[1]
			//写入全局变量在线用户列表
			onlineUsers[nickname] = conn
			fmt.Println("用户" + nickname + "登录")
			break
		case "lo":
			if len(cmdSplit) < 2 {
				fmt.Println("参数数量有问题")
				break
			}
			nickname := cmdSplit[1]
			//去掉换行符
			//删除全局变量在线用户列表
			delete(onlineUsers, nickname)

			fmt.Println("用户" + cmdSplit[1] + "登出")
			break
		case "co":
			onlineNickName := make([]string, 0)
			//遍历在线用户列表
			for k, _ := range onlineUsers {
				//fmt.Println("在线用户：\n" + k)
				onlineNickName = append(onlineNickName, k)
			}
			//输出给客户端
			conn.Write([]byte("在线用户：\n" + strings.Join(onlineNickName, "\n") + "\n"))

			break
		case "gs":
			if len(cmdSplit) < 3 {
				fmt.Println("参数数量有问题")
				break
			}
			fmt.Println("用户" + cmdSplit[1] + "发送消息：" + cmdSplit[2])
			str := cmdSplit[1] + "说:" + cmdSplit[2]

			//发送给除自己之外所有在线用户
			for k, v := range onlineUsers {
				if k == cmdSplit[1] {
					continue
				}
				v.Write([]byte(str + "\n"))
			}

			//conn.Write([]byte(str + "\n"))

			//记录群聊消息
			groupMsgQueue.Enqueue(str)
			break
		case "gr":
			//查出所有群聊消息
			groupMsg := make([]string, 0)

			for _, v := range groupMsgQueue.ToSlice() {
				groupMsg = append(groupMsg, v.(string))
			}

			//输出给客户端
			conn.Write([]byte("群聊消息：\n" + strings.Join(groupMsg, "\n") + "\n"))

			//fmt.Println("用户" + cmdSplit[1] + "接收消息：" + cmdSplit[2])
			break
		case "ps":
			if len(cmdSplit) < 4 {
				fmt.Println("参数数量有问题")
				break
			}
			str := cmdSplit[1] + "对你私信:" + cmdSplit[3]
			onlineUsers[cmdSplit[2]].Write([]byte(str + "\n"))
			fmt.Println("用户" + cmdSplit[1] + "给" + cmdSplit[2] + "发送私信：" + cmdSplit[3])
			break
		case "pr":
			fmt.Println("用户" + cmdSplit[1] + "给" + cmdSplit[2] + "接收私信：" + cmdSplit[3])
			break
		case "pp":
			fmt.Println("用户" + cmdSplit[1] + "动作")
			color := cmdSplit[2]
			action := cmdSplit[3]
			pos := cmdSplit[4]
			posSlice := strings.Split(pos, "*")
			x := posSlice[0]
			y := posSlice[1]
			fmt.Println("用户" + cmdSplit[1] + "动作" + color + action + "在" + x + "行" + y + "列")

			//发送给除自己之外所有在线用户
			for k, v := range onlineUsers {
				if k == cmdSplit[1] {
					continue
				}
				v.Write([]byte(m))
			}
			break
		default:
			fmt.Println("无法识别的命令")
		}

		//fmt.Println("接收到数据：", string(buf[:n]))
	}
}

//运行main方法，启动服务端。然后使用telnet命令连接服务端，输入数据，查看服务端是否能够接收到数据。
